#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the Xcoordination Application Space
 * ("XcoAppSpace") http://www.xcoordination.com
 *
 * Copyright (C) 2009 Xcoordination http://www.xcoordination.com
 *
 * XcoAppSpace is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * XcoAppSpace is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 * or write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * ---------------------------------------------------------------- */
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using XcoAppSpaces.Contracts.Transport;
using XcoAppSpaces.Contracts.Logging;

namespace XcoAppSpaces.Transport.WCF
{
	/// <summary>
	/// Implementation for the server side endpoint of the WCF service for communication with remote
	/// spaces. Named SpacePortal, because it provides a portal to the space for any incoming remote
	/// communication.
	/// Definition of the service behavior: Only one instance is running at the server, but can be
	/// used concurrent.
	/// </summary>
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class SpacePortal : IRemoteSpaceService
	{
		//private static readonly XcoSpaces.Kernel.Contracts.Logging.ILogger log = LoggerFactory.CreateInstance("XcoSpaces.Services.Kernel.Communication", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

		private XcoWCFTransportService commService = null;
		private Uri addr;
		//private List<String> subscribers = null;
		private IXcoLogger log = null;

		/// <summary>
		/// Creates a new SpacePortal.
		/// </summary>
        /// <param name="addr">The address in which the service host is running (here only needed for information purposes).</param>
		/// <param name="commService">The communication service.</param>
		/// <param name="log">Logger to be used for logging.</param>
		public SpacePortal(Uri addr, XcoWCFTransportService commService, IXcoLogger log)
		{
			this.commService = commService;
            this.addr = addr;
			this.log = log;
			//subscribers = new List<String>();
		}
	/*	public int SubscriberCount
		{
			get
			{
				return subscribers.Count;
			}
		}*/
		

		/// <summary>
		/// Does nothing, because it is only needed for connection initiation (which is managed
		/// internally by WCF).
		/// </summary>
		public void Connect()
		{
		/*	lock (subscribers)
			{
				subscribers.Add(OperationContext.Current.SessionId);
			}*/
		}

		/// <summary>
		/// Does nothing, because it is only needed for connection termination (which is managed
		/// internally by WCF).
		/// </summary>
		public void Disconnect()
		{
			/*lock (subscribers)
			{
				subscribers.Remove(OperationContext.Current.SessionId);
			}*/
		}

		/// <summary>
		/// Processes a message that has been received. The message is deserialized and the corresponding
		/// process method is called.
		/// </summary>
		/// <param name="msg">The message that has been received.</param>
		/// <param name="remoteAddress">The address from where the message has been received.</param>
        public void SendMessage(XcoMessage msg, string remoteAddress)
		{
			try
			{
				//Console.WriteLine("Received Message Object: " + tmp.ToString());
                if (msg != null)
				{
					log.Debug("Server on Port " + addr.ToString() + " - Received Remote Message " + msg + " from: " + remoteAddress);
					commService.RaiseMessageReceivedEvent(msg, remoteAddress);
				}
				else
				{
					//unknown/unexpected type
					log.Error("Received message can't convert.");
				}
			}
			catch (Exception ex)
			{
				//(Exception cannot be thrown anywhere when received here, so only log it)
				log.Error("Error when processing received message (deserialization failed?).", ex);
			}
		}
	}
}
